home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / opengl / xlib / cylinder2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  17.2 KB  |  657 lines

  1. /*
  2.  * Copyright 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. #include <stdio.h>
  18. #include <math.h>
  19. #include <GL/gl.h>
  20. #include <GL/glu.h>
  21. #include <GL/glx.h>
  22. #include <X11/Xlib.h>
  23. #include <X11/Xutil.h>
  24. #include <X11/keysym.h>
  25.  
  26. /*
  27.  * we'll define our own PI, could get it
  28.  * from math.h, but i'm not in the mood
  29.  */
  30. #define M_PI            3.14159265358979323846
  31.  
  32. /*
  33.  * some local functions
  34.  */
  35. void drawScene();
  36. void drawcyl();
  37. void drawBox();
  38.  
  39. /*
  40.  * define some lighting properties
  41.  */
  42. static float ambient[] = { 0.2, 0.2, 0.2, 1.0 };
  43. static float diffuse[] = { 0.6, 0.6, 0.6, 1.0 };
  44. static float specular[] = { 1.0, 1.0, 1.0, 1.0 };
  45. static float alm[] = { 0.1, 0.1, 0.1, 1};
  46. static float lpos[] = { 0, 0, 100, 0 };
  47. static float shininess[] = { 128.0 };
  48.  
  49. /*
  50.  * define material properties.  
  51.  */
  52. static float ambient2[] = { 0.4, 0.0, 0.4, 1.0 };
  53. static float diffuse2[] = { 0.7, 0.0, 0.7, 1.0 };
  54. static float specular2[] = { 1.0, 1.0, 1.0, 1.0 };
  55.  
  56. float bamat[] = {.4, .4, .4, 1.0};
  57. float bdmat[] = { 0.8, .8, .8, 1.0};
  58. float bsmat[] = { .1, .1, .1, 1.0};
  59.  
  60. float amat[] = {.1, .1, .2, 0.3};
  61. float dmat[] = { 0.3, .3, .5, 0.3};
  62. float smat[] = { 1.0, 1.0, 1.0, 0.3};
  63. float shin[] = { 128.0 };
  64.  
  65. float amat2[] = {.1, .1, .1, 0.5};
  66. float dmat2[] = { .3690, .0, .165, 0.5};
  67. float smat2[] = { .8, .8, .8, 0.5};
  68.  
  69.  
  70. /*
  71.  * the attribute list for the OpenGL visual.
  72.  * we only request 1 bit for each color and depth, we get more
  73.  * than 1 bit for each, i just put in for the minimum, the
  74.  * server should return a visual that meets these requirements or
  75.  * better...
  76.  */
  77. static int attributeList[] = {GLX_RGBA, GLX_DOUBLEBUFFER, 
  78.     GLX_RED_SIZE, 1,
  79.     GLX_GREEN_SIZE, 1,
  80.     GLX_BLUE_SIZE, 1,
  81.     GLX_DEPTH_SIZE, 1,
  82.     None };
  83.  
  84. /*
  85.  * the attribute list for the overlay OpenGL visual.
  86.  * notice that we define 2 of them, GLX_LEVEL 2 and 1.
  87.  * we will try to get an overlay visual (GLX_LEVEL 2).  if we can't get one,
  88.  * we will try to overlay planes (GLX_LEVEL 1)
  89.  */
  90. static int al2[] = {GLX_LEVEL, 2,  None };
  91.  
  92. static int al3[] = {GLX_LEVEL, 1,  None };
  93.  
  94. /*
  95.  * a convenience function, just waits for the window to map.  this
  96.  * is handy, since we don't want to risk OpenGL drawing into an
  97.  * unmapped window, that would be bad...
  98.  */
  99. static Bool WaitForNotify (Display *d, XEvent *e, char *arg)
  100. {
  101.     return (e->type == MapNotify) && (e->xmap.window == (Window) arg);
  102. }
  103.  
  104. /*
  105.  * default window size...
  106.  */
  107. #define WINSIZE 600
  108.  
  109. /*
  110.  * a few global variables
  111.  */
  112. int WIRE_FRAME = 0;
  113. int TRANSPARENT = 0;
  114. int RESET = True;
  115. int WHITE_PIXEL_NUM;
  116.  
  117. int  xorigin, yorigin;        /* window x and y locations */
  118. unsigned int  width, height;  /* window width and height  */
  119. float rx, ry;                 /* adjusted x and y locations */
  120. Display *dpy;                 /* X Display */
  121. Window win;                   /* OpenGL X Window ID */
  122. Window owin;                  /* OpenGL overlay X Window ID */ 
  123. GLXContext cx;                /* context for the OpenGL window */
  124. GLXContext ocx;               /* context for the overlay OpenGL window */
  125.  
  126. Window winList[3];            /* X window ID list, needed to map window 
  127.                   colormaps */
  128.  
  129.  
  130. /*
  131.  * main routine.  
  132.  */
  133. main()
  134. {
  135.  
  136.     XVisualInfo *vi;              /* X Visual  */
  137.     Colormap cmap, ocmap;         /* X Colormap */
  138.     XSetWindowAttributes swa;     /* X Window Attributes */
  139.     XEvent event;                 /* X event             */
  140.     char    xbuf[20];             /* character buffer */
  141.     int     nchar = 20;           /* size of character buffer */
  142.     KeySym  key;                  /* keyboard key hit */
  143.     XComposeStatus cs;            /* X keyboard compose structure */
  144.     XWindowAttributes winattrs;   /* X Window attribute structure */
  145.     XColor  spix, pixel;          /* X pixel structure */
  146.     float fx, fy;                 /* adjusted x & y cursor positions */
  147.  
  148.  
  149.   /*
  150.    * open a connection to the local display
  151.    */
  152.     dpy = XOpenDisplay (0);
  153.  
  154.   /* 
  155.    * get an OpenGL main plane visual, if we fail, big problems, 
  156.    * exit... 
  157.    */
  158.     if (!(vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList))) {
  159.         printf("\n can't get requested visual type, bye...\n");
  160.         exit(0);
  161.         }
  162.  
  163.   /* create a GLX context */
  164.     cx = (GLXContext) glXCreateContext (dpy, vi, None, GL_TRUE);
  165.  
  166.   /* create a colormap using this visual */
  167.     cmap = XCreateColormap (dpy, RootWindow(dpy, vi->screen), vi->visual,
  168.                             AllocNone);
  169.  
  170.   /* set up the window attributes and create an X Window */
  171.     swa.colormap = cmap;
  172.     swa.border_pixel = 1;
  173.     swa.event_mask = StructureNotifyMask;
  174.     win = XCreateWindow (dpy, RootWindow(dpy,vi->screen), 
  175.                          0, 0, WINSIZE, WINSIZE,
  176.                          0, vi->depth, InputOutput, vi->visual,
  177.                          CWBorderPixel|CWColormap|CWEventMask, &swa);
  178.  
  179.     XMapWindow (dpy,win);
  180.  
  181.   /* 
  182.    * try to create an overlay window.  first try for GLX_LEVEL 2, a visual
  183.    * in the overlay planes.  if that fails, go for GLX_LEVEL 1, a visual in
  184.    * the popup planes.  if that fails, game over...
  185.    */
  186.  
  187.     if (!(vi = glXChooseVisual (dpy, DefaultScreen(dpy), al2))) {
  188.        
  189.        /*
  190.         * overlay failed, try popup
  191.         */
  192.         fprintf(stderr, "bummer, can't get overlay visual, trying popup...\n"); 
  193.  
  194.         if (!(vi = glXChooseVisual (dpy, DefaultScreen(dpy), al3))) {
  195.            /*
  196.             * popup failed too, bummer 
  197.             */
  198.             fprintf(stderr,
  199.                    "bummer, can't get requested popup visual either, bye...\n");
  200.             exit(0);
  201.             }
  202.         else {  /* got popup visual! */
  203.             fprintf(stderr,"got popup visual!\n");
  204.             }
  205.         }
  206.     else {
  207.         fprintf(stderr, "got overlay visual!\n"); 
  208.          }
  209.  
  210.    /* 
  211.     * create a GLX context for the overlay window
  212.     */
  213.     ocx = (GLXContext) glXCreateContext (dpy, vi, None, GL_TRUE);
  214.  
  215.    /* 
  216.     * create a colormap using this visual
  217.     */
  218.     ocmap = XCreateColormap (dpy, RootWindow(dpy, vi->screen), vi->visual,
  219.                             AllocNone);
  220.  
  221.    /* 
  222.     * set up window attributes and create a X Window with overlay visual
  223.     */
  224.     swa.colormap = ocmap;
  225.     swa.border_pixel = 0;
  226.     swa.win_gravity = UnmapGravity;
  227.     swa.bit_gravity = NorthWestGravity;
  228.     swa.background_pixel = BlackPixel(dpy, vi->screen);
  229.  
  230.     owin = XCreateWindow (dpy, win, 0, 0, WINSIZE, WINSIZE,
  231.                          0, vi->depth, InputOutput, vi->visual,
  232.                          CWBorderPixel|CWColormap|CWEventMask, &swa);
  233.  
  234.    /*
  235.     * map window
  236.     */
  237.     XMapWindow (dpy,owin);
  238.  
  239.  
  240.    /*
  241.     * wait for main planes window to map so that we can start drawing into
  242.     * it.
  243.     */
  244.     XIfEvent(dpy, &event, WaitForNotify, (char *) win);
  245.  
  246.    /* 
  247.     * install the colormap windows property so that overlay colormap
  248.     * takes hold when we move cursor into window
  249.     */
  250.     winList[0] = win;
  251.     winList[1] = owin;
  252.     XSetWMColormapWindows(dpy, win, winList, 2);
  253.  
  254.    /*
  255.     * get the 'white' pixel value, we will need this
  256.     * to set colormap index for overlay drawing
  257.     */
  258.     XAllocNamedColor(dpy, ocmap, "white", &spix, &pixel);
  259.     WHITE_PIXEL_NUM = pixel.pixel;
  260.  
  261.    /* 
  262.     * connect the context to the main planes window 
  263.     */
  264.     if (!glXMakeCurrent(dpy, win, cx) == GL_TRUE) {
  265.         return 0;
  266.     }
  267.  
  268.  
  269.    /*
  270.     * get the window size and location so that we can
  271.     * make the cylinder track the mouse movements *somewhat* acurately
  272.     */
  273.  
  274.     XGetWindowAttributes(dpy, win, &winattrs);
  275.     xorigin = winattrs.x;
  276.     yorigin = winattrs.y;
  277.     width = winattrs.width;
  278.     height = winattrs.height;
  279.  
  280.  
  281.    /*
  282.     * all right! finally some OpenGL stuff!!
  283.     * enable zbuffer depth test
  284.     */
  285.     glEnable(GL_DEPTH_TEST);
  286.     glDepthFunc(GL_LEQUAL);
  287.  
  288.    /*
  289.     * set up projection matrix, perspective projection if you please...
  290.     */
  291.     glMatrixMode(GL_PROJECTION);
  292.     glLoadIdentity();
  293.     gluPerspective((double) 450, (double) (width/(float)height), 
  294.                  (double) .25, (double) 15.0);
  295.  
  296.    /*
  297.     * ok, model transformations from now on...
  298.     */
  299.     glMatrixMode(GL_MODELVIEW);
  300.  
  301.    /*
  302.     * set up lighting attributes
  303.     */
  304.     glLightfv(GL_LIGHT1, GL_POSITION, lpos);
  305.     glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
  306.     glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
  307.     glLightfv(GL_LIGHT1, GL_SPECULAR, specular);
  308.  
  309.  
  310.    /*
  311.     * set up light model attributes
  312.     */
  313.     glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
  314.     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, alm);
  315.     glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); 
  316.  
  317.    /*
  318.     * turn on the light!
  319.     */
  320.     glEnable(GL_LIGHTING);
  321.     glEnable(GL_LIGHT1);
  322.  
  323.  
  324.    /*
  325.     * hit the model matrix with an initial translation, 3 units back in
  326.     * Z direction to add a little spice...
  327.     */
  328.     glTranslatef(0., 0., -3.);
  329.  
  330.  
  331.     /*
  332.      * set X input stuff
  333.      */
  334.      XSelectInput(dpy, win, ExposureMask);
  335.  
  336.      XSelectInput(dpy, win, ExposureMask |StructureNotifyMask |
  337.                                ButtonPressMask | Button1MotionMask |
  338.                    SubstructureNotifyMask | KeyPressMask |
  339.                                KeyReleaseMask | ButtonReleaseMask );
  340.  
  341.     /*
  342.      * do the same for overlay window 
  343.      */
  344.      XSelectInput(dpy, owin, ExposureMask);
  345.      XSelectInput(dpy, owin, ExposureMask |StructureNotifyMask |
  346.                                ButtonPressMask | Button1MotionMask |
  347.                    SubstructureNotifyMask | KeyPressMask |
  348.                                KeyReleaseMask | ButtonReleaseMask );
  349.  
  350.  
  351.  
  352.     /*
  353.      * ready to go, print out instructions to the screen
  354.      */
  355.  
  356.      printf("\npush leftmouse button and drag to move cylinder!\n");
  357.      printf("\n 'o' key to toggle overlay drawing");
  358.      printf("\n 't' key to toggle scene transparency");
  359.      printf("\n 'Esc' key to quit\n");
  360.      fflush(stdout);
  361.  
  362.  
  363.     /*
  364.      * the dreaded X event loop...
  365.      */
  366.      while (1) {         /* loop forever... */
  367.  
  368.             XNextEvent(dpy, &event);
  369.  
  370.             switch (event.type) {
  371.  
  372.         case Expose:
  373.                     if (event.xexpose.count)
  374.                         continue;
  375.                 drawScene();
  376.                     if (!WIRE_FRAME) {   /* have to manually clear overlay */
  377.                                          /* since code is too 'dumb' to    */
  378.                          /* redraw overlay in drawScene    */
  379.                         glXMakeCurrent(dpy, owin, ocx);
  380.                         glClearColor(0.0, 0.0, 0.0, 0.0);
  381.                         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  382.                         }
  383.             break;
  384.  
  385.          case ConfigureNotify:
  386.  
  387.                    /*
  388.                     * resize or reposition, so get pertinent window
  389.                     * info and update scene.   don't forget to
  390.                     * resize overlay window!
  391.                     */
  392.  
  393.                     XGetWindowAttributes(dpy, win, &winattrs);
  394.                     xorigin = winattrs.x;
  395.                     yorigin = winattrs.y;
  396.                     width = winattrs.width;
  397.                     height = winattrs.height;
  398.             glXMakeCurrent(dpy, win, cx);
  399.                     glViewport(0, 0, width, height);
  400.                 drawScene();
  401.  
  402.                     XResizeWindow(dpy, owin, width, height);
  403.                     glXMakeCurrent(dpy, owin, ocx);
  404.                     glViewport(0, 0, width, height);
  405.             break;
  406.  
  407.  
  408.         case KeyPress:
  409.  
  410.                     XLookupString((XKeyEvent *) &event, xbuf, nchar, &key, &cs);
  411.  
  412.                     switch (key) {
  413.  
  414.                         case XK_Escape:   /* quit */
  415.                             printf("\n bye...\n");
  416.                             exit(0);
  417.                             break;
  418.  
  419.                         case XK_T:       /* toggle scene transparency */
  420.                         case XK_t:
  421.                             TRANSPARENT = !TRANSPARENT;
  422.                             drawScene();
  423.                             break;
  424.  
  425.                         case XK_O:       /* toggle overlay drawing */
  426.                         case XK_o:
  427.                             WIRE_FRAME = !WIRE_FRAME;
  428.                     drawScene();
  429.                             break;
  430.                         }
  431.  
  432.                     break;
  433.  
  434.  
  435.         case MotionNotify:
  436.                    /*
  437.                     * get cursor position and rotate scene
  438.                     */
  439.                     fx = (float) event.xmotion.x;
  440.                     fy = (float) event.xmotion.y;
  441.                     rx = -500.0 * (2.0*(fy - yorigin)/height-1.0);
  442.             ry = 500.0 * (2.0*(fx - xorigin)/width-1.0);
  443.  
  444.             drawScene();
  445.             break;
  446.  
  447.         default:
  448.             break;
  449.  
  450.                 }
  451.             }
  452.  
  453. }
  454.  
  455.  
  456. /*
  457.  * main scene drawing routine.
  458.  */
  459. void
  460. drawScene()
  461. {
  462.  
  463.     
  464.     if (!WIRE_FRAME) {
  465.        /*
  466.         * no wire frame, so update main planes scene.
  467.         * set the main plane window as the current window to draw into,
  468.         * clear the window and depth buffer
  469.         */
  470.         glXMakeCurrent(dpy, win, cx);
  471.         glClearColor(0.0, 0.0, 0.0, 0.0);
  472.         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  473.  
  474.        /*
  475.         * push down a new matrix onto the matrix stack.  then apply
  476.         * a couple of rotations
  477.         */  
  478.         glPushMatrix();
  479.         glRotatef((float) ry, 0., 1., 0.);
  480.         glRotatef((float) -rx, 1., 0., 0.);
  481.     
  482.        /*
  483.         * disable blending and turn on depth check
  484.         */
  485.         glDisable(GL_BLEND);
  486.         glBlendFunc(GL_ONE, GL_ZERO);
  487.         glDepthMask(1);
  488.  
  489.        /*
  490.         * set up materials
  491.         */
  492.         setMaterial(GL_FRONT, ambient2, diffuse2, specular2, shininess);
  493.         setMaterial(GL_BACK, bamat, bdmat, bsmat, shin);
  494.  
  495.        /*
  496.         * scale down cylinder slightly
  497.         */
  498.         glScalef(.5, 1.0, .5);
  499.         drawcyl();
  500.  
  501.        /*
  502.         * pop matrix off of stack
  503.         */
  504.         glPopMatrix();
  505.  
  506.        /*
  507.         * new matrix, apply same rotations
  508.         */
  509.         glPushMatrix();
  510.  
  511.         glRotatef((float) ry, 0., 1., 0.);
  512.         glRotatef((float) -rx, 1., 0., 0.);
  513.  
  514.        /*
  515.         * if transparency enabled, turn off depth check, enable blending
  516.         */
  517.         if (TRANSPARENT) {
  518.             glDepthMask(0);
  519.             glEnable(GL_BLEND);
  520.             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  521.             }
  522.         else  {  /* else no transparency */
  523.             glDisable(GL_BLEND);
  524.             glDepthMask(1);
  525.             }
  526.  
  527.        /*
  528.         * set up materials, draw cylinder 
  529.         */
  530.         setMaterial(GL_FRONT, amat, dmat, smat, shin);
  531.         setMaterial(GL_BACK, amat, dmat, smat, shin);
  532.  
  533.         drawcyl();
  534.  
  535.        /*
  536.         * disable blending
  537.         */
  538.         if (TRANSPARENT)
  539.             glDisable(GL_BLEND);
  540.  
  541.  
  542.        /*
  543.         * pop off matrix, swap buffers to show updated scene
  544.         */
  545.         glPopMatrix();
  546.  
  547.         glXSwapBuffers(dpy, win);
  548.         }
  549.  
  550.     else { 
  551.  
  552.        /* 
  553.         * draw into overlay window.  make overlay window current, and
  554.         * clear;
  555.         */
  556.  
  557.         glXMakeCurrent(dpy, owin, ocx);
  558.         glClearColor(0.0, 0.0, 0.0, 0.0);
  559.         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  560.  
  561.        /*
  562.         * push down a matrix onto the stack, and apply rotations
  563.         */
  564.         glPushMatrix();
  565.  
  566.         glRotatef((float) ry, 0., 1., 0.);
  567.         glRotatef((float) -rx, 1., 0., 0.);
  568.  
  569.        /*
  570.         * draw the wire box, flush the graphics pipe, pop the matrix off
  571.         * of the matrix stack
  572.         */
  573.         drawBox();
  574.         glFlush();
  575.  
  576.         glPopMatrix();
  577.  
  578.         }
  579. }
  580.  
  581.  
  582. /*
  583.  * routine to draw cylinder.  note that normals are specified with
  584.  * glNormal3fv() to take advantage of lighting.
  585.  */
  586. void
  587. drawcyl()
  588. {
  589. double dy = .2;
  590. double theta, dtheta = 2*M_PI/20;
  591. double x, y, z;
  592. float n[3], v[3];
  593. int i, j;
  594.  
  595.     for (i = 0, y = -1;  i < 10;  i++, y += dy)  {
  596.             glEnable(GL_LIGHTING);
  597.         glBegin(GL_TRIANGLE_STRIP);
  598.         for (j = 0, theta = 0;  j <= 20;  j++, theta += dtheta)  {
  599.             if (j == 20)  theta = 0;
  600.             x = cos(theta);
  601.             z = sin(theta);
  602.             n[0] = x;  n[1] = 0;  n[2] = z;
  603.             glNormal3fv(n);
  604.             v[0] = x;  v[1] = y;  v[2] = z;
  605.             glVertex3fv(v);
  606.             v[1] = y + dy;
  607.             glVertex3fv(v);
  608.         }
  609.         glEnd();
  610.     }
  611. }
  612.  
  613.  
  614. /*
  615.  * convenience function to set material properties
  616.  */
  617. setMaterial(GLenum face, float *ambient, float *diffuse, 
  618.                float *specular, float *shininess)
  619. {
  620.         glMaterialfv(face, GL_AMBIENT, ambient);
  621.         glMaterialfv(face, GL_DIFFUSE, diffuse);
  622.         glMaterialfv(face, GL_SPECULAR, specular);
  623.         glMaterialfv(face, GL_SHININESS, shininess);
  624. }
  625.  
  626.  
  627. /*
  628.  * routine to draw the wire box in the overlay window.  notice that
  629.  * we use color index mode, glIndexi() to set colors here even though
  630.  * the main plane window uses RGB
  631.  */
  632. void
  633. drawBox()
  634. {
  635.  
  636.      float v[2];
  637.  
  638.      glIndexi(WHITE_PIXEL_NUM);
  639.  
  640.      glBegin(GL_LINE_LOOP);
  641.          v[0] = v[1] = -.5;
  642.          glVertex2fv(v);
  643.          v[0] = .5;
  644.          glVertex2fv(v);
  645.          v[1] = .5;
  646.          glVertex2fv(v);
  647.          v[0] = -.5;
  648.          glVertex2fv(v);
  649.      glEnd(); 
  650.      
  651.  
  652.  
  653. }
  654.  
  655.  
  656.  
  657.